package cn.tedu.datamanager.serve.ipml;

import cn.tedu.datamanager.ex.ServiceException;
import cn.tedu.datamanager.mapper.AdminMapper;
import cn.tedu.datamanager.pojo.dto.AdminAddNewDTO;
import cn.tedu.datamanager.pojo.dto.AdminLoginDTO;
import cn.tedu.datamanager.pojo.entity.Admin;
import cn.tedu.datamanager.pojo.entity.AdminRole;
import cn.tedu.datamanager.pojo.vo.AdminListItemVO;
import cn.tedu.datamanager.pojo.vo.LevelListItemVO;
import cn.tedu.datamanager.pojo.vo.ServeListItemVO;
import cn.tedu.datamanager.security.AdminDetails;
import cn.tedu.datamanager.serve.IAdminService;
import cn.tedu.datamanager.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;


@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {
    @Autowired
    AdminMapper adminMapper;
    @Value("${datamanager.jwt.secret-key}")
    String secretKey;
    @Value("${datamanager.jwt.duration-in-minute}")
    long durationInMinute;
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    PasswordEncoder passwordEncoder;


    @Override
    public List<AdminListItemVO> list() {
        log.debug("开始处理【查询服务项目列表】的业务");
        // 调用Mapper查询服务项目列表
        List<AdminListItemVO> list = adminMapper.list();
        // 返回
        return list;
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        Date date = new Date();
        String name = adminLoginDTO.getName();
        log.debug("开始处理【员工登录】的业务,adminLoginDTO={}", adminLoginDTO);
        Authentication authentication
                = new UsernamePasswordAuthenticationToken(
                adminLoginDTO.getName(), adminLoginDTO.getPassword());
        Authentication authenticateResult
                = authenticationManager.authenticate(authentication);
        log.debug("执行认证成功，AuthenticationManager返回：{}", authenticateResult);
        Object principal = authenticateResult.getPrincipal();
        log.debug("认证结果中的Principal数据类型：{}", principal.getClass().getName());
        log.debug("认证结果中的Principal数据：{}", principal);
        AdminDetails adminDetails = (AdminDetails) principal;

        //员工完成登录的操作后,修改员工的登录时间
        System.out.println("修改用户登录时间!");
        adminMapper.updateuptime(name, date);

        log.debug("准备生成JWT数据");
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", adminDetails.getId()); // 向JWT中封装id
        claims.put("username", adminDetails.getUsername()); // 向JWT中封装username
        claims.put("authorities", JSON.toJSONString(adminDetails.getAuthorities())); // 向JWT中封装权限

        Date expirationDate = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("完成jwt的生成任务!");

        //判断登录人员的身份,使得前端跳转不同的页面
        String level = adminMapper.selectAdminLevel(name);
        System.out.println("正在验证账号,所查询账号的level是:" + level);
        if ((level.equals("管理员")) || (level.equals("总负责人"))) {
            return jwt;
        }
        String message = "登录成功!返回员工页面!";
        log.warn(message);
        throw new ServiceException(ServiceCode.STAFF, message);
    }

    @Override
    public int setEnable(Long id) {

        log.debug("开始处理【启用员工】的业务,id={}", id);
        AdminListItemVO queryResult = adminMapper.getStandardById(id);
        if (queryResult == null) {
            String message = "启用员工失败,尝试访问的数据不存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        if (queryResult.getEnable() == 1) {
            String message = "该员工已经启用,请勿重复操作!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }


        Admin admin = new Admin();
        admin.setId(id);
        admin.setEnable(1);

        int rows = adminMapper.updateById(admin);
        if (rows != 1) {
            String message = "启用员工失败,服务器忙,请稍后再试!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
        return rows;
    }

    @Override
    public int setDisable(Long id) {
        log.debug("开始处理【停用员工】的业务,id={}", id);
        AdminListItemVO queryResult = adminMapper.getStandardById(id);
        if (queryResult == null) {
            String message = "停用员工失败,尝试访问的数据不存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        if (queryResult.getEnable() == 0) {
            String message = "该员工已经停用,请勿重复操作!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        Admin admin = new Admin();
        admin.setId(id);
        admin.setEnable(0);

        int rows = adminMapper.updateById(admin);
        if (rows != 1) {
            String message = "停用员工失败,服务器忙,请稍后再试!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
        return rows;
    }

    @Override
    //添加员工
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.debug("开始处理【添加员工】的业务，参数：{}", adminAddNewDTO);

        log.debug("即将检查用户名是否被占用……");
        {
            // 从参数对象中获取username
            String username = adminAddNewDTO.getName();
            // 调用adminMapper的countByUsername()方法执行统计查询
            int count = adminMapper.selectByUsername(username);
            // 判断统计结果是否不等于0
            if (count != 0) {
                // 是：抛出异常
                String message = "添加员工失败，用户名【" + username + "】已经被占用！";
                log.debug(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        log.debug("即将检查手机号码是否被占用……");
        {
            // 从参数对象中获取手机号码
            String phone = adminAddNewDTO.getPhonenumber();
            // 调用adminMapper的countByPhone()方法执行统计查询
            int count = adminMapper.getPhoneNumber(phone);
            // 判断统计结果是否不等于0
            if (count != 0) {
                // 是：抛出异常
                String message = "添加员工失败，手机号码【" + phone + "】已经被占用！";
                log.debug(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        // 创建Admin对象
        Admin admin = new Admin();

        // 通过BeanUtils.copyProperties()方法将参数对象的各属性值复制到Admin对象中
        BeanUtils.copyProperties(adminAddNewDTO, admin);

        String rawPassword = admin.getPassword();
        String encodedPassword = passwordEncoder.encode(rawPassword);
        admin.setPassword(encodedPassword);

        // 调用adminMapper的insert()方法插入数据
        log.debug("即将插入员工数据，参数：{}", admin);
        int rows = adminMapper.insert(admin);
        // 判断插入数据的结果是否符合预期
        if (rows != 1) {
            String message = "添加员工失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }

    }

    @Override
    public void delete(Long id) {
        log.debug("开始处理【删除员工】的业务，参数：{}", id);
        // 判断参数id是否为1
        if (id == 666) {
            String message = "删除员工失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 根据参数id查询员工数据
        AdminListItemVO queryResult = adminMapper.getStandardById(id);
        // 判断员工数据是否不存在
        if (queryResult == null) {
            String message = "删除员工失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 执行删除员工
        int rows = adminMapper.deleteById(id);
        if (rows != 1) {
            String message = "删除员工失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

    }


    @Override
    public AdminListItemVO selectupdate(Long Id) {
        AdminListItemVO queryResult = adminMapper.getStandardById(Id);
        if (queryResult == null) {
            String message = "查询服务项目失败,尝试访问的数据不存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        AdminListItemVO rows = adminMapper.selectupdate(Id);
        return rows;
    }


    @Override
    public void update(AdminAddNewDTO adminAddNewDTO) {
        log.debug("开始处理【修改员工数据】的业务，参数：{}", adminAddNewDTO);
        log.debug("即将检查用户名是否存在……");
        AdminListItemVO queryResult = adminMapper.getStandardById(adminAddNewDTO.getId());
        if (queryResult == null) {
            String message = "修改员工数据失败,尝试访问的数据不存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        Admin album = new Admin();
//        // 将参数DTO中的数据复制到Album对象中
        BeanUtils.copyProperties(adminAddNewDTO, album);
        String rawPassword = album.getPassword();
        String encodedPassword = passwordEncoder.encode(rawPassword);
        album.setPassword(encodedPassword);
//        log.debug("即将插入服务项目数据：{}", album);
//        // 调用Mapper对象的insert()方法，插入服务项目数据
        log.debug("即将修改的数据为:" + album);
        adminMapper.update(album);
    }


    @Override
    public List<LevelListItemVO> levellist() {
        log.debug("开始处理【查询员工职位列表】的业务");
        // 调用Mapper查询项目类别列表
        List<LevelListItemVO> list = adminMapper.levellist();
        // 返回
        return list;
    }


}

